{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "# Robodyno 电机 API文档"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 目录\n",
    "- [初始化电机对象](#初始化电机对象)\n",
    "- [电机状态](#电机状态)\n",
    "- [获取API版本](#获取API版本)\n",
    "- [电机软急停](#电机软急停)\n",
    "- [电机重启](#电机重启)\n",
    "- [清除错误](#清除错误)\n",
    "- [保存设置](#保存设置)\n",
    "- [设置电机CAN_ID](#设置电机CAN_ID)\n",
    "- [电机使能](#电机使能)\n",
    "- [电机失能](#电机失能)\n",
    "- [电机校准](#电机校准)\n",
    "- [进入直接位置模式](#进入直接位置模式)\n",
    "- [进入滤波位置模式](#进入滤波位置模式)\n",
    "- [进入轨迹位置模式](#进入轨迹位置模式)\n",
    "- [设置位置](#设置位置)\n",
    "- [进入直接速度模式](#进入直接速度模式)\n",
    "- [进入匀加减速速度模式](#进入匀加减速速度模式)\n",
    "- [设置速度](#设置速度)\n",
    "- [进入力矩控制模式](#进入力矩控制模式)\n",
    "- [设置力矩](#设置力矩)\n",
    "- [读取总线电压](#读取总线电压)\n",
    "- [读取电机温度](#读取电机温度)\n",
    "- [读取电机状态参数](#读取电机状态参数)\n",
    "- [读取电机位置](#读取电机位置)\n",
    "- [读取电机速度](#读取电机速度)\n",
    "- [读取电机力矩](#读取电机力矩)\n",
    "- [读取电机控制模式](#读取电机控制模式)\n",
    "- [读取加速度输入模式参数](#读取加速度输入模式参数)\n",
    "- [读取滤波输入模式参数](#读取滤波输入模式参数)\n",
    "- [读取轨迹模式参数](#读取轨迹模式参数)\n",
    "- [读取电机PID参数](#读取电机PID参数)\n",
    "- [设置电机PID参数](#设置电机PID参数)\n",
    "- [读取电机速度电流限制](#读取电机速度电流限制)\n",
    "- [读取电机速度限制](#读取电机速度限制)\n",
    "- [读取电机电流限制](#读取电机电流限制)\n",
    "- [设置电机速度电流限制](#设置电机速度电流限制)\n",
    "- [设置电机速度限制](#设置电机速度限制)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 初始化电机对象\n",
    "\n",
    "出厂ID：0x10\n",
    "\n",
    "\n",
    "参数：\n",
    "- reduction: 减速比\n",
    "\n",
    "常用减速比：\n",
    "- 二级行星：-12.45\n",
    "- 三级行星：-44\n",
    "- RV50：53.325\n",
    "- RV100：110.205\n",
    "- 谐波50：50\n",
    "- 谐波100：100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [],
   "source": [
    "from robodyno import Robot\n",
    "from robodyno.nodes import MotorFactory\n",
    "robot = Robot()\n",
    "motor = robot.add_device('motor0', MotorFactory(), 0x10, reduction=-44)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 电机状态\n",
    "`motor.status()`\n",
    "最近一次心跳包的内容\n",
    "\n",
    "返回值：\n",
    "- 电机状态dict\n",
    "    - state: 工作模式（1：空闲，8：使能）\n",
    "    - error: 错误码（1：电压不足，14：急停）\n",
    "    - motor_err: 电机相关错误码\n",
    "    - encoder_err: 编码器相关错误码\n",
    "    - controller_err: 控制器相关错误码\n",
    "    - control_mode: 控制模式（1：力矩控制，2：速度控制，3：位置控制）\n",
    "    - input_mode: 输入模式（1：直接值，2：带加速度，3：带滤波，5：梯形轨迹）\n",
    "    - timestamp: 时间戳，上一次收到心跳包的时间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1634601873.3142447\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'state': 1,\n",
       " 'error': 0,\n",
       " 'motor_err': 0,\n",
       " 'encoder_err': 0,\n",
       " 'controller_err': 0,\n",
       " 'control_mode': 3,\n",
       " 'input_mode': 1,\n",
       " 'timestamp': 1634601872.612408}"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.status()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 获取API版本\n",
    "`get_api_version(timeout = 0)`\n",
    "\n",
    "参数：\n",
    "- timeout: 请求超时时间(s)，0代表无超时时间\n",
    "\n",
    "返回值：\n",
    "- API版本dict\n",
    "    - device_uuid: 设备uuid\n",
    "    - main_version: 主版本号\n",
    "    - sub_version: 副版本号"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'device_uuid': 1, 'main_version': 0, 'sub_version': 3}"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_api_ver(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 电机软急停\n",
    "`estop()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.estop()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 电机重启\n",
    "`reboot()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.reboot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 清除错误\n",
    "`clear_errors()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.clear_errors()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 保存设置\n",
    "`save_configuration()`\n",
    "\n",
    "设置参数后默认不会保存，直到调用此函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.save_configuration()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置电机CAN_ID\n",
    "`set_can_id(id, rate)`\n",
    "\n",
    "参数：\n",
    "- id：电机新CAN_ID (0x01~0x3F)\n",
    "- rate: 心跳包发送周期，ms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_can_id(id = 0x10, rate = 1000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 电机使能\n",
    "`enable()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.enable()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 电机失能\n",
    "`disable()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.disable()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 电机校准\n",
    "`calibrate()`\n",
    "\n",
    "校准后需保存参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.calibrate()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取总线电压\n",
    "`get_vbus(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 总线电压值(V)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11.760278"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_vbus(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机温度\n",
    "`get_temperature(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 电机温度(°C)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25.645182"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_temperature(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机状态参数\n",
    "`get_status(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 电机状态参数(位置rad, 速度rad/s, 力矩Nm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.017474906493244825, -0.0021789499827921041, 0.039215607010618991)"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_status(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机位置\n",
    "`get_pos(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 位置(rad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.069557394641307016"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_pos(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机速度\n",
    "`get_vel(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 速度(rad/s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0054473749569802594"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_vel(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机力矩\n",
    "`get_torque(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 力矩(Nm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0025244379172367128"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_torque(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机相电流\n",
    "`get_phase_current(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 相电流(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.get_phase_current(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机控制模式\n",
    "`get_controller_modes(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 控制模式(control_mode, input_mode)\n",
    "    - control_mode: 控制模式（1：力矩控制，2：速度控制，3：位置控制）\n",
    "    - input_mode: 输入模式（1：直接值，2：带加速度，3：带滤波，5：梯形轨迹)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 3)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_controller_modes(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取加速度输入模式参数\n",
    "`get_ramp_mode_ramp(timeout)`\n",
    "\n",
    "参数:\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- ramp: 加速度(rad/s^2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.50000000182561766"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_ramp_mode_ramp()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取滤波输入模式参数\n",
    "`get_filter_mode_bandwidth(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- bandwidth: 滤波带宽 / 输入频率(Hz)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.0"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_filter_mode_bandwidth()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取轨迹模式参数\n",
    "`get_traj_mode_params(timeout)`\n",
    "\n",
    "参数:\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 轨迹参数(最大速度, 加速度, 减速度)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1.9999659557397373, 0.49999148893493434, 0.49999148893493434)"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_traj_mode_params()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机PID参数\n",
    "`get_controller_pid(timeout)`\n",
    "\n",
    "参数：\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 电机PID(位置环P, 速度环P, 速度环I)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(100.0, 0.020004, 0.0050011)"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_controller_pid(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置电机PID参数\n",
    "`set_controller_pid(pos_p, vel_p, vel_i)`\n",
    "\n",
    "参数:\n",
    "- pos_p: 位置环比例系数\n",
    "- vel_p: 速度环比例系数\n",
    "- vel_i: 速度环积分系数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_controller_pid(100,0.02,0.005)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机速度电流限制\n",
    "`get_limits(timeout)`\n",
    "\n",
    "参数:\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- (输入端最大速度(r/s), 最大电流(A))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(6.2218442, 14.0)"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_limits(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机速度限制\n",
    "`get_vel_limit(timeout)`\n",
    "\n",
    "参数:\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 输出端最大速度(rad/s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.1400000030422306"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_vel_limit(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 读取电机电流限制\n",
    "`get_current_limit(timeout)`\n",
    "\n",
    "参数:\n",
    "- timeout\n",
    "\n",
    "返回值：\n",
    "- 最大电流(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "motor.get_current_limit()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置电机速度电流限制\n",
    "`set_limits(vel_limit, torque_limit)`\n",
    "\n",
    "参数：\n",
    "- vel_limit: 输入端最大速度(r/s)\n",
    "- torque_limit: 最大电流(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_limits(30, 10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置电机速度限制\n",
    "`set_vel_limit(vel_limit)`\n",
    "\n",
    "参数：\n",
    "- vel_limit: 输出端最大速度(rad/s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_vel_limit(3.14)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进入直接位置模式\n",
    "`position_mode()`\n",
    "\n",
    "直接PID控制位置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.position_mode()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进入滤波位置模式\n",
    "`position_filter_mode(bandwidth)`\n",
    "\n",
    "参数：\n",
    "- bandwidth: 滤波带宽 / 控制频率(Hz)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.position_filter_mode(4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进入轨迹位置模式\n",
    "`position_traj_mode(max_vel, accel, decel)`\n",
    "\n",
    "参数:\n",
    "- max_vel: 最高速度\n",
    "- accel: 加速度\n",
    "- decel: 减速度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.position_traj_mode(2,0.5,0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置位置\n",
    "`set_pos(position)`\n",
    "\n",
    "参数:\n",
    "- position: 目标位置(rad)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_pos(-3.14)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进入直接速度模式\n",
    "`velocity_mode()`\n",
    "\n",
    "速度PID控制"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.velocity_mode()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进入匀加减速速度模式\n",
    "`velocity_ramp_mode(ramp)`\n",
    "\n",
    "参数:\n",
    "- ramp: 加速度(rad/s^2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.velocity_ramp_mode(0.5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置速度\n",
    "`set_vel(velocity)`\n",
    "\n",
    "参数：\n",
    "- velocity: 目标速度(rad/s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_vel(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进入力矩控制模式\n",
    "`torque_mode()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.torque_mode()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 设置力矩\n",
    "`set_torque(torque)`\n",
    "\n",
    "参数：\n",
    "- torque: 目标力矩(Nm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.set_torque(0.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 恢复出厂设置\n",
    "`reset_motor()`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "motor.reset_motor()"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "767d51c1340bd893661ea55ea3124f6de3c7a262a8b4abca0554b478b1e2ff90"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
